package cn.lijiancn01.demo.system.service;

import cn.hutool.json.JSONUtil;
import cn.lijiancn01.demo.framework.exception.BizException;
import cn.lijiancn01.demo.framework.model.PageResult;
import cn.lijiancn01.demo.framework.model.R;
import cn.lijiancn01.demo.framework.util.BeanUtil;
import cn.lijiancn01.demo.system.codegen.GenResult;
import cn.lijiancn01.demo.system.codegen.MyCodegenEngine;
import cn.lijiancn01.demo.system.codegen.MyCustomConfig;
import cn.lijiancn01.demo.system.convert.GlobalConfigConvert;
import cn.lijiancn01.demo.system.convert.MyCustomConfigConvert;
import cn.lijiancn01.demo.system.entity.Template;
import cn.lijiancn01.demo.system.mapper.TemplateMapper;
import cn.lijiancn01.demo.system.vo.PreviewTemplateVO;
import cn.lijiancn01.demo.system.vo.QueryTemplateVO;
import cn.lijiancn01.demo.system.vo.SaveTemplateVO;
import cn.lijiancn01.demo.system.vo.TemplateVO;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.mybatisflex.codegen.config.GlobalConfig;
import com.mybatisflex.core.query.If;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.service.IService;
import com.mybatisflex.core.util.UpdateEntity;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.sql.DataSource;
import java.util.Collection;
import java.util.List;

import static cn.lijiancn01.demo.system.entity.table.TemplateTableDef.TEMPLATE;

@Service
public class TemplateService implements IService<Template> {
    @Autowired
    private TemplateMapper templateMapper;
    @Autowired
    private DataSourceService dataSourceService;

    @Override
    public TemplateMapper getMapper() {
        return templateMapper;
    }

    public List<TemplateVO> findByGroupCode(String groupCode) {
        return BeanUtil.copyList(getMapper().findByGroupCode(groupCode), TemplateVO.class);
    }

    public TemplateVO findByGroupCodeAndCode(String groupCode, String code) {
        return BeanUtil.copyBean(getMapper().findByGroupCodeAndCode(groupCode, code), TemplateVO.class);
    }

    public TemplateVO findById(Long id) {
        return BeanUtil.copyBean(getById(id), TemplateVO.class);
    }

    public TemplateVO findById(Long id, String dataSourceCode, String tableName) {
        TemplateVO templateVO = findById(id);
        pushFileContent(Lists.newArrayList(templateVO), dataSourceCode, tableName);
        return templateVO;
    }

    public TemplateVO previewByContent(PreviewTemplateVO previewTemplateVO) {
        TemplateVO templateVO = findById(previewTemplateVO.getId());
        templateVO.setContent(previewTemplateVO.getContent());
        pushFileContent(Lists.newArrayList(templateVO), previewTemplateVO.getDataSourceCode(), previewTemplateVO.getTableName());
        return templateVO;
    }

    public PageResult<TemplateVO> findByCondition(QueryTemplateVO queryVO) {
        QueryWrapper query = QueryWrapper.create()
                .from(TEMPLATE)
                .where(TEMPLATE.CODE.like(queryVO.getCode(), If::hasText))
                .and(TEMPLATE.GROUP_CODE.eq(queryVO.getGroupCode(), If::hasText))
                .orderBy(TEMPLATE.ID, false);
        return getMapper().findByCondition(queryVO.getPage(), queryVO.getPerPage(), query, TemplateVO.class);
    }

    /**
     * 填充根据文档生成的文件内容
     *
     * @param templates
     * @param dataSourceCode
     * @param tableName
     */
    private void pushFileContent(Collection<TemplateVO> templates, String dataSourceCode, String tableName) {
        if (StringUtils.isBlank(dataSourceCode) || StringUtils.isBlank(tableName)) {
            return;
        }
        DataSource ds = dataSourceService.getDs(dataSourceCode);
        if (ds == null) {
            return;
        }
        //创建配置内容
        GlobalConfig globalConfig = GlobalConfigConvert.build("cn.lijiancn01.demo.system", Sets.newHashSet(tableName));
        for (TemplateVO templateVO : templates) {
            MyCustomConfig myCustomConfig = MyCustomConfigConvert.of(templateVO);
            globalConfig.setCustomConfig(myCustomConfig.getCode(), myCustomConfig);
        }
        HashBasedTable<String, String, GenResult> hashBasedTable = new MyCodegenEngine(ds, globalConfig).generate();
        //填充模板生成内容
        for (TemplateVO templateVO : templates) {
            GenResult genResult = hashBasedTable.get(templateVO.getCode(), tableName);
            if (genResult != null) {
                templateVO.setParamsJson(JSONUtil.toJsonStr(genResult.getParams()));
                templateVO.setCreateFileContent(genResult.getCreateFileContent());
                templateVO.setCreateFilePath(genResult.getCreateFilePath());
            }
        }
    }

    public R edit(SaveTemplateVO saveTemplateVO) {
        Template templateDO = getById(saveTemplateVO.getId());
        if (templateDO == null) {
            throw new BizException("操作的数据不存在");
        }
        Template updateBean = UpdateEntity.of(Template.class);
        BeanUtil.copyBean(saveTemplateVO, updateBean);
        return R.data(updateById(updateBean));
    }

    public R add(SaveTemplateVO saveTemplateVO) {
        Template addBean = BeanUtil.copyBean(saveTemplateVO, Template.class);
        addBean.setId(null);
        return R.data(save(addBean));
    }

    public R remove(Long id) {
        Template bean = getById(id);
        if (bean == null) {
            throw new BizException("操作的数据不存在");
        }
        return R.data(removeById(id));
    }

    public void insertBatch(List<Template> batchTemplates) {
        saveBatch(batchTemplates);
    }


}
